unit Core_FileOperaions;

interface
uses
  Windows, Core_Types, SysUtils, Forms;

procedure CopyFiles(Src, Dst : PFileArray; Move : Boolean = False);
procedure DeleteFiles(FileList : PFileArray);
procedure ClearDirRecursive(Path : String);
function BytesToSize(Size : Cardinal):PChar;
function CountDirSize(Path : String) : Integer;
procedure SetDirSize(FileList : PFileArray; Index : Integer);

implementation
uses
   Interface_Progress, Interface_MainWnd;

procedure SetDirSize(FileList : PFileArray; Index : Integer);
begin
  FileList^.Files[Index].Size := CountDirSize(FileList^.Path + FileList^.Files[Index].Name);
end;

function CountDirSize(Path : String) : Integer;
var
  sr : TSearchRec;
begin
  Result := 0;
  if FindFirst(Path + '\*.*', faDirectory or faAnyFile, sr) = 0 then
  begin
    repeat
      if (sr.Name <> '..') and (sr.Name <> '.') then
      begin
        if (sr.Attr and faDirectory) <> 0 then
          Result := Result + CountDirSize(Path + '\' + sr.Name) else
        begin
          Result := Result + sr.Size;
        end;
      end;
    until
      FindNext(sr) <> 0;

    FindClose(sr);
  end;
end;

function CountDirFiles(Path : String) : Integer;
var
  sr : TSearchRec;
begin
  Result := 0;
  if FindFirst(Path + '*.*', faDirectory or faAnyFile, sr) = 0 then
  begin
    repeat
      if (sr.Name <> '..') and (sr.Name <> '.') then
      begin
        if (sr.Attr and faDirectory) <> 0 then
          Result := Result + CountDirFiles(Path + sr.Name + '\') else
        begin
          Result := Result + 1;
        end;
      end;
    until
      FindNext(sr) <> 0;

    FindClose(sr);
  end;
end;

procedure CopyDirectory(fromdir, todir : string; Move : Boolean = False);
var
  sr : TSearchRec;
begin
  if FindFirst(fromdir + '*.*', faAnyFile or faDirectory, sr) = 0 then
  begin
    repeat
      if (sr.Name <> '.') and (sr.Name <> '..') then
      begin
        if (sr.Attr and faDirectory) <> 0 then
        begin
          MkDir(todir + sr.Name);
          CopyDirectory(fromdir + sr.Name + '\', todir + sr.Name + '\', Move);
          
          if Move then
            RmDir(fromdir + sr.Name);
        end else
        begin
          WndProgress.lblInfo.Caption := fromdir + sr.Name;
          CopyFile(PChar(fromdir + sr.Name), PChar(todir + sr.Name), False);
          
          if Move then
            DeleteFile(fromdir + sr.Name);
            
          WndProgress.ProgressBar.StepIt;
          Application.ProcessMessages;
        end;
      end;
    until
      FindNext(sr) <> 0;

    FindClose(sr);
  end;
end;

procedure CopyFiles(Src, Dst : PFileArray; Move : Boolean = False);
var
  i,cnt:Integer;
begin
  cnt := 0;

  WndProgress.lblOperation.Caption := 'Copy';
  WndProgress.Show;

  for i := 0 to High(Src^.Files) do
  begin
    if Src^.Files[i].Selected then
    begin
      if Src^.Files[i].Dir then
        cnt := cnt + CountDirFiles(Src^.Path + Src^.Files[i].Name) else
          cnt := cnt + 1;
    end;
  end;

  WndProgress.ProgressBar.Max := cnt;
  WndProgress.ProgressBar.Position := 0;

  for i := 0 to High(Src^.Files) do
  begin
    if Src^.Files[i].Selected then
    begin
      if Src^.Files[i].Dir then
      begin
        if not DirectoryExists(Dst^.Path + Src^.Files[i].Name) then
          MkDir(Dst^.Path + Src^.Files[i].Name);

        CopyDirectory(Src^.Path + Src^.Files[i].Name + '\', Dst^.Path + Src^.Files[i].Name + '\', Move);
      end else
      begin
        CopyFile(PChar(Src^.Path + Src^.Files[i].Name), PChar(Dst^.Path + Src^.Files[i].Name), False);
        WndProgress.ProgressBar.StepIt;
      end;
    end;
  end;

  WndProgress.Close;
end;

function BytesToSize(Size : Cardinal):PChar;
var
  sName : String;
begin
  sName := 'b';

  if Size > 1024 then
  begin
    sName := 'KB';
    Size := Size div 1024;

    if Size > 1024 then
    begin
      sName := 'MB';
      Size := Size div 1024;

      if Size > 1024 then
      begin
        sName := 'GB';
        Size := Size div 1024;

        if Size > 1024 then
        begin
          sName := 'TB';
          Size := Size div 1024;
        end;
      end;
    end;
  end;

  sName := IntToStr(Size) + ' ' + sName;
  Result := GetMemory(Length(sName)+1);
  ZeroMemory(Result, Length(sName)+1);
  CopyMemory(Result, @sName[1], Length(sName));
end;

procedure ClearDirRecursive(Path : String);
var
  sr : TSearchRec;
begin
  if FindFirst(Path + '*.*', faAnyFile or faDirectory, sr) = 0 then
  begin
    repeat
      if (sr.Name <> '.') and (sr.Name <> '..') then
      begin
        if (sr.Attr and faDirectory) <> 0 then
        begin
          ClearDirRecursive(Path + sr.Name + '\');
          RmDir(Path + sr.Name);
        end else
        begin
          DeleteFile(Path + sr.Name);
          WndProgress.lblInfo.Caption := Path + sr.Name;
          WndProgress.ProgressBar.StepIt;
          Application.ProcessMessages;
        end;
      end;
    until
      FindNext(sr) <> 0;

    FindClose(sr);
  end;
end;

procedure DeleteFiles(FileList : PFileArray);
var
  i, count:Integer;
begin
  WndProgress.lblOperation.Caption := 'Count size...';
  for i := 0 to High(FileList^.Files) do
  begin
    if FileList^.Files[i].Selected then
    begin
      if FileList^.Files[i].Dir then
      begin
        if MessageBox(WndMain.Handle, 'Folder may be not empty! Delete anyway?', 'Warning', MB_ICONWARNING or MB_YESNO) = IDNO then Exit;
        count := count + CountDirSize(FileList^.Path + FileList^.Files[i].Name);
      end else
      begin
        count := count + FileList^.Files[i].Size;
      end;
    end;
  end;
  WndProgress.ProgressBar.Position := 0;
  WndProgress.ProgressBar.Max := count;
  for i := 0 to High(FileList^.Files) do
  begin
    if FileList^.Files[i].Selected then
    begin
      if FileList^.Files[i].Dir then
      begin
        ClearDirRecursive(FileList^.Path + FileList^.Files[i].Name + '\');
        RmDir(FileList^.Path + FileList^.Files[i].Name);
      end else
      begin
        DeleteFile(FileList^.Path + FileList^.Files[i].Name);
        WndProgress.ProgressBar.StepIt;
        WndProgress.lblInfo.Caption := 'Deleting ' + FileList^.Files[i].Name;
      end;
    end;
  end;
end;

end.
